use std::{rc::Rc, time::SystemTime};
use winit::{event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode}, event_loop::ControlFlow};

use crate::{VK_LOGV, vulkan::VkConfig, VK_LOGD};

use self::{render::{RenderSystem, RenderSystemCreateInfo}, scene::{SceneSystem, SceneSystemCreateInfo}, window::{WindowSystem, WindowSystemCreateInfo}};

pub mod window;
pub mod render;
pub mod scene;

const MAX_FRAMES_IN_FLIGHT: usize = 2;

/// 整个世界环境的Context，各个系统应该设计在这个下面
pub struct GlobalContext {
    pub g_window_system             : WindowSystem,
    pub g_render_system             : RenderSystem,
    pub g_scene_system              : SceneSystem,

    start_time : SystemTime,
}

impl GlobalContext {
    pub fn new(vk_config: &mut VkConfig) -> Self {
        let window_system_ci    = WindowSystemCreateInfo::new();
        let window_system       = WindowSystem::new(&window_system_ci);

        let render_system_ci    = RenderSystemCreateInfo { window_system: &window_system };
        let render_system   = RenderSystem::new(vk_config, &render_system_ci);

        let scene_system_ci     = SceneSystemCreateInfo { render_system: &render_system };
        let scene_system    = SceneSystem::new(&scene_system_ci);

        Self {
            g_window_system         : window_system,
            g_render_system         : render_system,
            g_scene_system          : scene_system,

            start_time: SystemTime::now(),
        }
    }

    pub fn run(mut self) {
        VK_LOGD!("####################################################");
        VK_LOGD!("#################### Application ###################");
        VK_LOGD!("####################################################");
    
        // 亟待简化
        self.g_window_system.w_event_loop.take().unwrap().run(move |event, _, control_flow|
            match event {
                | Event::WindowEvent { event, .. } => {
                    match event {
                        | WindowEvent::CloseRequested => {
                            *control_flow = ControlFlow::Exit;
                        },
                        | WindowEvent::KeyboardInput { input, .. } => {
                            match input {
                                | KeyboardInput { virtual_keycode, state, .. } => {
                                    match (virtual_keycode, state) {
                                        | (Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
                                            *control_flow = ControlFlow::Exit
                                        },
                                        | _ => {},
                                    }
                                },
                            }
                        },
                        | WindowEvent::Resized(_) => {
                            
                        }
                        | _ => {},
                    }
                },
                | Event::MainEventsCleared => {
                    self.g_window_system.w_window.request_redraw();
                },
                | Event::RedrawRequested(_window_id) => {
                    // VK_LOGV!("Hello MainLoop!");
                    let delta_time = 
                        SystemTime::now().duration_since(self.start_time).expect("failed duration since").as_secs_f32();
                    self.start_time = SystemTime::now();
                    self.g_scene_system.tick(delta_time);
                    self.g_render_system.tick(&self.g_scene_system, delta_time);
                    self.g_window_system.w_window.set_title((1.0/delta_time).to_string().as_str());
                },
                | Event::LoopDestroyed => {
                    VK_LOGV!("LoopDestroyed");
                },
                | _ => (),
            }
        );
    }
}